using JobsTutorialSample.Step1;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using Random = UnityEngine.Random;

namespace JobsTutorialSample.Step3
{
    /*
     * 使用多工作线程 + Burst编译（例子的特殊性附带：缓存友好）
     */
    public class Spawner : MonoBehaviour
    {
        public static Transform[] SeekerTransforms;
        public static Transform[] TargetTransforms;

        public GameObject SeekerPrefab;
        public GameObject TargetPrefab;
        public int SeekerCount;
        public int TargetCount;
        public Vector2 Bounds;

        NativeArray<float3> mSeekerPositions;
        NativeArray<float3> mNearestTargetPositions;
        NativeArray<float3> mTargetPositions;

        void Start()
        {
            Random.InitState(123);

            SeekerTransforms = new Transform[SeekerCount];
            for (int i = 0; i < SeekerCount; i++)
            {
                GameObject go = Instantiate(SeekerPrefab);
                Seeker seeker = go.GetComponent<Seeker>();
                Vector2 dir = Random.insideUnitCircle;
                seeker.Direction = new Vector3(dir.x, 0, dir.y);
                go.transform.localPosition = new Vector3(Random.Range(0, Bounds.x), 0, Random.Range(0, Bounds.y));
                SeekerTransforms[i] = go.transform;
            }

            TargetTransforms = new Transform[TargetCount];
            for (int i = 0; i < TargetCount; i++)
            {
                GameObject go = Instantiate(TargetPrefab);
                Target target = go.GetComponent<Target>();
                Vector2 dir = Random.insideUnitCircle;
                target.Direction = new Vector3(dir.x, 0, dir.y);
                go.transform.localPosition = new Vector3(Random.Range(0, Bounds.x), 0, Random.Range(0, Bounds.y));
                TargetTransforms[i] = go.transform;
            }

            mSeekerPositions = new NativeArray<float3>(SeekerCount, Allocator.Persistent);
            mNearestTargetPositions = new NativeArray<float3>(SeekerCount, Allocator.Persistent);
            mTargetPositions = new NativeArray<float3>(TargetCount, Allocator.Persistent);
        }

        void OnDestroy()
        {
            mSeekerPositions.Dispose();
            mNearestTargetPositions.Dispose();
            mTargetPositions.Dispose();
        }

        void Update()
        {
            for (int i = 0; i < mSeekerPositions.Length; i++)
                mSeekerPositions[i] = SeekerTransforms[i].localPosition;
            for (int i = 0; i < mTargetPositions.Length; i++)
                mTargetPositions[i] = TargetTransforms[i].localPosition;

            FindNearestJobParallel findNearestJob = new FindNearestJobParallel()
            {
                SeekerPositions = mSeekerPositions,
                TargetPositions = mTargetPositions,
                NearestTargetPositions = mNearestTargetPositions,
            };
            var handle = findNearestJob.Schedule(mSeekerPositions.Length, 50);
            handle.Complete();

            for (int i = 0; i < mSeekerPositions.Length; i++)
            {
                Debug.DrawLine(mSeekerPositions[i], mNearestTargetPositions[i]);
            }
        }
    }
}